home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / Utilities / ttf2pt1PPC / src / ttf2pt1.c < prev    next >
C/C++ Source or Header  |  2001-07-05  |  74KB  |  2,378 lines

  1. /*
  2.  * True Type Font to Adobe Type 1 font converter 
  3.  * By Mark Heath <mheath@netspace.net.au> 
  4.  * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> 
  5.  * With help from Frank M. Siegert <fms@this.net> 
  6.  *
  7.  * see COPYRIGHT
  8.  *
  9. ***********************************************************************
  10.  *
  11.  * Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com>
  12.  *
  13.  * Added post-processing of resulting outline to correct the errors
  14.  * both introduced during conversion and present in the original font,
  15.  * autogeneration of hints (has yet to be improved though) and BlueValues,
  16.  * scaling to 1000x1000 matrix, option to print the result on STDOUT,
  17.  * support of Unicode to CP1251 conversion, optimization  of the
  18.  * resulting font code by space (that improves the speed too). Excluded
  19.  * the glyphs that are unaccessible through the encoding table from
  20.  * the output file. Added the built-in Type1 assembler (taken from
  21.  * the `t1utils' package).
  22.  *
  23. ***********************************************************************
  24.  *
  25.  * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
  26.  *
  27.  * Added generation of .afm file (font metrics)
  28.  * Read encoding information from encoding description file
  29.  * Fixed bug in error message about unknown language ('-l' option)
  30.  * Added `:' after %%!PS-AdobeFont-1.0
  31.  * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128...
  32.  *
  33. ***********************************************************************
  34.  *
  35.  * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
  36.  *
  37.  * Added generation of .afm file (font metrics)
  38.  *
  39. ***********************************************************************
  40.  *
  41.  * Bug Fixes: 
  42. ************************************************************************
  43.  *
  44.  * Sun, 21 Jun 1998 Thomas Henlich <thenlich@Rcs1.urz.tu-dresden.de> 
  45.  * 1. "width" should be "short int" because otherwise: 
  46.  *     characters with negative widths (e.g. -4) become *very* wide (65532) 
  47.  * 2. the number of /CharStrings is numglyphs and not numglyphs+1 
  48.  *
  49. ***********************************************************************
  50.  *
  51.  *
  52.  *
  53.  * The resultant font file produced by this program still needs to be ran
  54.  * through t1asm (from the t1utils archive) to produce a completely valid
  55.  * font. 
  56.  *
  57.  */
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <sys/types.h>
  62. #include <sys/stat.h>
  63. #include <fcntl.h>
  64. #include <time.h>
  65. #include <ctype.h>
  66. #include <math.h>
  67.  
  68. #ifdef _GNU_SOURCE
  69. #include <getopt.h>
  70. #endif
  71.  
  72. #ifndef WINDOWS
  73. #    include <unistd.h>
  74. #    include <netinet/in.h>
  75. #    define BITBUCKET "/dev/null"
  76. #    include <sys/wait.h>
  77. #else
  78. #    define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */
  79. #    include "windows.h"
  80. #    define BITBUCKET "NUL"
  81. #endif
  82.  
  83. #ifdef AMIGA
  84. #undef  BITBUCKET
  85. #define BITBUCKET "NIL:"
  86.  
  87. #include <proto/exec.h>
  88.  
  89. #ifdef __PPC__
  90. #include <proto/powerpc.h>
  91.  
  92. #define AllocVec( size, req )        AllocVecPPC( size, req, (ULONG)32 )
  93. #define FindTask                        FindTaskPPC
  94. #endif
  95.  
  96. struct StackSwapStruct stackswap;
  97. APTR   new_stack = NULL;
  98. #endif
  99.  
  100. #include "pt1.h"
  101. #include "global.h"
  102. #include "version.h"
  103.  
  104. /* globals */
  105.  
  106. /* table of front-ends */
  107.  
  108. extern struct frontsw ttf_sw;
  109. #if defined(USE_FREETYPE)
  110.     extern struct frontsw freetype_sw;
  111. #endif
  112.  
  113. struct frontsw *frontswtab[] = {
  114. #if defined(USE_FREETYPE) && defined(PREFER_FREETYPE)
  115.     &freetype_sw,
  116. #endif
  117.     &ttf_sw,
  118. #if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE)
  119.     &freetype_sw,
  120. #endif
  121.     NULL /* end of table */
  122. };
  123.  
  124. struct frontsw *cursw=0; /* the active front end */
  125. char *front_arg=""; /* optional argument */
  126.  
  127. /* options */
  128. int      encode = 0;    /* encode the resulting file */
  129. int      pfbflag = 0;    /* produce compressed file */
  130. int      wantafm=0;    /* want to see .afm instead of .t1a on stdout */
  131. int      correctvsize=0;    /* try to correct the vertical size of characters */
  132. int      wantuid = 0;    /* user wants UniqueID entry in the font */
  133. int      allglyphs = 0;    /* convert all glyphs, not only 256 of them */
  134. int      warnlevel = 3;    /* the level of permitted warnings */
  135. int      forcemap = 0; /* do mapping even on non-Unicode fonts */
  136. /* options - maximal limits */
  137. int      max_stemdepth = 128;    /* maximal depth of stem stack in interpreter (128 - limit from X11) */
  138. /* options - debugging */
  139. int      absolute = 0;    /* print out in absolute values */
  140. int      reverse = 1;    /* reverse font to Type1 path directions */
  141. /* options - suboptions of Outline Processing, defaults are set in table */
  142. int      optimize;    /* enables space optimization */
  143. int      smooth;    /* enable smoothing of outlines */
  144. int      transform;    /* enables transformation to 1000x1000 matrix */
  145. int      hints;    /* enables autogeneration of hints */
  146. int      subhints;    /* enables autogeneration of substituted hints */
  147. int      trybold;    /* try to guess whether the font is bold */
  148. int      correctwidth;    /* try to correct the character width */
  149.  
  150. /* not quite options to select a particular source encoding */
  151. int      force_pid = -1; /* specific platform id */
  152. int      force_eid = -1; /* specific encoding id */
  153.  
  154. /* table of Outline Processing (may think also as Optimization) options */
  155. static struct {
  156.     char disbl; /* character to disable - enforced lowercase */
  157.     char enbl;  /* character to enable - auto-set as toupper(disbl) */
  158.     int *valp; /* pointer to the actual variable containing value */
  159.     int  dflt; /* default value */
  160.     char *descr; /* description */
  161. } opotbl[] = {
  162.     { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
  163.     { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
  164.     { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
  165.     { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
  166.     { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
  167.     { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
  168.     { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
  169. };
  170.  
  171. int      debug = DEBUG;    /* debugging flag */
  172.  
  173. FILE    *pfa_file, *afm_file;
  174. int      numglyphs;
  175. struct font_metrics fontm;
  176.  
  177. /* non-globals */
  178. static char    *strUID = 0;    /* user-supplied UniqueID */
  179. static unsigned long numUID;    /* auto-generated UniqueID */
  180.  
  181. static int      ps_fmt_3 = 0;
  182. static double   scale_factor, original_scale_factor;
  183.  
  184. static char    *glyph_rename[ENCTABSZ];
  185.  
  186. /* the names assigned if the original font
  187.  * does not specify any
  188.  */
  189.  
  190. static char    *Fmt3Encoding[256] = {
  191.     "c0", "c1", "c2", "c3",
  192.     "c4", "c5", "c6", "c7",
  193.     "c8", "c9", "c10", "c11",
  194.     "c12", "CR", "c14", "c15",
  195.     "c16", "c17", "c18", "c19",
  196.     "c20", "c21", "c22", "c23",
  197.     "c24", "c25", "c26", "c27",
  198.     "c28", "c29", "c30", "c31",
  199.     "space", "exclam", "quotedbl", "numbersign",
  200.     "dollar", "percent", "ampersand", "quotesingle",
  201.     "parenleft", "parenright", "asterisk", "plus",
  202.     "comma", "hyphen", "period", "slash",
  203.     "zero", "one", "two", "three",
  204.     "four", "five", "six", "seven",
  205.     "eight", "nine", "colon", "semicolon",
  206.     "less", "equal", "greater", "question",
  207.     "at", "A", "B", "C",
  208.     "D", "E", "F", "G",
  209.     "H", "I", "J", "K",
  210.     "L", "M", "N", "O",
  211.     "P", "Q", "R", "S",
  212.     "T", "U", "V", "W",
  213.     "X", "Y", "Z", "bracketleft",
  214.     "backslash", "bracketright", "asciicircum", "underscore",
  215.     "grave", "a", "b", "c",
  216.     "d", "e", "f", "g",
  217.     "h", "i", "j", "k",
  218.     "l", "m", "n", "o",
  219.     "p", "q", "r", "s",
  220.     "t", "u", "v", "w",
  221.     "x", "y", "z", "braceleft",
  222.     "bar", "braceright", "asciitilde", "c127",
  223.     "c128", "c129", "quotesinglbase", "florin",
  224.     "quotedblbase", "ellipsis", "dagger", "daggerdbl",
  225.     "circumflex", "perthousand", "Scaron", "guilsinglleft",
  226.     "OE", "c141", "c142", "c143",
  227.     "c144", "quoteleft", "quoteright", "quotedblleft",
  228.     "quotedblright", "bullet", "endash", "emdash",
  229.     "tilde", "trademark", "scaron", "guilsinglright",
  230.     "oe", "c157", "c158", "Ydieresis",
  231.     "nbspace", "exclamdown", "cent", "sterling",
  232.     "currency", "yen", "brokenbar", "section",
  233.     "dieresis", "copyright", "ordfeminine", "guillemotleft",
  234.     "logicalnot", "sfthyphen", "registered", "macron",
  235.     "degree", "plusminus", "twosuperior", "threesuperior",
  236.     "acute", "mu", "paragraph", "periodcentered",
  237.     "cedilla", "onesuperior", "ordmasculine", "guillemotright",
  238.     "onequarter", "onehalf", "threequarters", "questiondown",
  239.     "Agrave", "Aacute", "Acircumflex", "Atilde",
  240.     "Adieresis", "Aring", "AE", "Ccedilla",
  241.     "Egrave", "Eacute", "Ecircumflex", "Edieresis",
  242.     "Igrave", "Iacute", "Icircumflex", "Idieresis",
  243.     "Eth", "Ntilde", "Ograve", "Oacute",
  244.     "Ocircumflex", "Otilde", "Odieresis", "multiply",
  245.     "Oslash", "Ugrave", "Uacute", "Ucircumflex",
  246.     "Udieresis", "Yacute", "Thorn", "germandbls",
  247.     "agrave", "aacute", "acircumflex", "atilde",
  248.     "adieresis", "aring", "ae", "ccedilla",
  249.     "egrave", "eacute", "ecircumflex", "edieresis",
  250.     "igrave", "iacute", "icircumflex", "idieresis",
  251.     "eth", "ntilde", "ograve", "oacute",
  252.     "ocircumflex", "otilde", "odieresis", "divide",
  253.     "oslash", "ugrave", "uacute", "ucircumflex",
  254.     "udieresis", "yacute", "thorn", "ydieresis"
  255. };
  256.  
  257. #ifdef notdef /* { */
  258. /* This table is not used anywhere in the code
  259.  * so it's ifdef-ed out by default but left in
  260.  * the source code for reference purposes (and
  261.  * possibly for future use)
  262.  */
  263.  
  264. static char    *ISOLatin1Encoding[256] = {
  265.     ".null", ".notdef", ".notdef", ".notdef",
  266.     ".notdef", ".notdef", ".notdef", ".notdef",
  267.     ".notdef", ".notdef", ".notdef", ".notdef",
  268.     ".notdef", "CR", ".notdef", ".notdef",
  269.     ".notdef", ".notdef", ".notdef", ".notdef",
  270.     ".notdef", ".notdef", ".notdef", ".notdef",
  271.     ".notdef", ".notdef", ".notdef", ".notdef",
  272.     ".notdef", ".notdef", ".notdef", ".notdef",
  273.     "space", "exclam", "quotedbl", "numbersign",
  274.     "dollar", "percent", "ampersand", "quoteright",
  275.     "parenleft", "parenright", "asterisk", "plus",
  276.     "comma", "hyphen", "period", "slash",
  277.     "zero", "one", "two", "three",
  278.     "four", "five", "six", "seven",
  279.     "eight", "nine", "colon", "semicolon",
  280.     "less", "equal", "greater", "question",
  281.     "at", "A", "B", "C",
  282.     "D", "E", "F", "G",
  283.     "H", "I", "J", "K",
  284.     "L", "M", "N", "O",
  285.     "P", "Q", "R", "S",
  286.     "T", "U", "V", "W",
  287.     "X", "Y", "Z", "bracketleft",
  288.     "backslash", "bracketright", "asciicircum", "underscore",
  289.     "grave", "a", "b", "c",
  290.     "d", "e", "f", "g",
  291.     "h", "i", "j", "k",
  292.     "l", "m", "n", "o",
  293.     "p", "q", "r", "s",
  294.     "t", "u", "v", "w",
  295.     "x", "y", "z", "braceleft",
  296.     "bar", "braceright", "asciitilde", "c127",
  297.     "c128", "c129", "quotesinglbase", "florin",
  298.     "quotedblbase", "ellipsis", "dagger", "daggerdbl",
  299.     "circumflex", "perthousand", "Scaron", "guilsinglleft",
  300.     "OE", "c141", "c142", "c143",
  301.     "c144", "quoteleft", "quoteright", "quotedblleft",
  302.     "quotedblright", "bullet", "endash", "emdash",
  303.     "tilde", "trademark", "scaron", "guilsinglright",
  304.     "oe", "c157", "c158", "Ydieresis",
  305.     "nbspace", "exclamdown", "cent", "sterling",
  306.     "currency", "yen", "brokenbar", "section",
  307.     "dieresis", "copyright", "ordfeminine", "guillemotleft",
  308.     "logicalnot", "sfthyphen", "registered", "macron",
  309.     "degree", "plusminus", "twosuperior", "threesuperior",
  310.     "acute", "mu", "paragraph", "periodcentered",
  311.     "cedilla", "onesuperior", "ordmasculine", "guillemotright",
  312.     "onequarter", "onehalf", "threequarters", "questiondown",
  313.     "Agrave", "Aacute", "Acircumflex", "Atilde",
  314.     "Adieresis", "Aring", "AE", "Ccedilla",
  315.     "Egrave", "Eacute", "Ecircumflex", "Edieresis",
  316.     "Igrave", "Iacute", "Icircumflex", "Idieresis",
  317.     "Eth", "Ntilde", "Ograve", "Oacute",
  318.     "Ocircumflex", "Otilde", "Odieresis", "multiply",
  319.     "Oslash", "Ugrave", "Uacute", "Ucircumflex",
  320.     "Udieresis", "Yacute", "Thorn", "germandbls",
  321.     "agrave", "aacute", "acircumflex", "atilde",
  322.     "adieresis", "aring", "ae", "ccedilla",
  323.     "egrave", "eacute", "ecircumflex", "edieresis",
  324.     "igrave", "iacute", "icircumflex", "idieresis",
  325.     "eth", "ntilde", "ograve", "oacute",
  326.     "ocircumflex", "otilde", "odieresis", "divide",
  327.     "oslash", "ugrave", "uacute", "ucircumflex",
  328.     "udieresis", "yacute", "thorn", "ydieresis"
  329. };
  330.  
  331. #endif /* } notdef */
  332.  
  333. static char    *adobe_StandardEncoding[256] = {
  334.     ".notdef", ".notdef", ".notdef", ".notdef",
  335.     ".notdef", ".notdef", ".notdef", ".notdef",
  336.     ".notdef", ".notdef", ".notdef", ".notdef",
  337.     ".notdef", ".notdef", ".notdef", ".notdef",
  338.     ".notdef", ".notdef", ".notdef", ".notdef",
  339.     ".notdef", ".notdef", ".notdef", ".notdef",
  340.     ".notdef", ".notdef", ".notdef", ".notdef",
  341.     ".notdef", ".notdef", ".notdef", ".notdef",
  342.     "space", "exclam", "quotedbl", "numbersign",
  343.     "dollar", "percent", "ampersand", "quoteright",
  344.     "parenleft", "parenright", "asterisk", "plus",
  345.     "comma", "hyphen", "period", "slash",
  346.     "zero", "one", "two", "three",
  347.     "four", "five", "six", "seven",
  348.     "eight", "nine", "colon", "semicolon",
  349.     "less", "equal", "greater", "question",
  350.     "at", "A", "B", "C", "D", "E", "F", "G",
  351.     "H", "I", "J", "K", "L", "M", "N", "O",
  352.     "P", "Q", "R", "S", "T", "U", "V", "W",
  353.     "X", "Y", "Z", "bracketleft",
  354.     "backslash", "bracketright", "asciicircum", "underscore",
  355.     "quoteleft", "a", "b", "c", "d", "e", "f", "g",
  356.     "h", "i", "j", "k", "l", "m", "n", "o",
  357.     "p", "q", "r", "s", "t", "u", "v", "w",
  358.     "x", "y", "z", "braceleft",
  359.     "bar", "braceright", "asciitilde", ".notdef",
  360.     ".notdef", ".notdef", ".notdef", ".notdef",
  361.     ".notdef", ".notdef", ".notdef", ".notdef",
  362.     ".notdef", ".notdef", ".notdef", ".notdef",
  363.     ".notdef", ".notdef", ".notdef", ".notdef",
  364.     ".notdef", ".notdef", ".notdef", ".notdef",
  365.     ".notdef", ".notdef", ".notdef", ".notdef",
  366.     ".notdef", ".notdef", ".notdef", ".notdef",
  367.     ".notdef", ".notdef", ".notdef", ".notdef",
  368.     ".notdef", "exclamdown", "cent", "sterling",
  369.     "fraction", "yen", "florin", "section",
  370.     "currency", "quotesingle", "quotedblleft", "guillemotleft",
  371.     "guilsinglleft", "guilsinglright", "fi", "fl",
  372.     ".notdef", "endash", "dagger", "daggerdbl",
  373.     "periodcentered", ".notdef", "paragraph", "bullet",
  374.     "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
  375.     "ellipsis", "perthousand", ".notdef", "questiondown",
  376.     ".notdef", "grave", "acute", "circumflex",
  377.     "tilde", "macron", "breve", "dotaccent",
  378.     "dieresis", ".notdef", "ring", "cedilla",
  379.     ".notdef", "hungarumlaut", "ogonek", "caron",
  380.     "emdash", ".notdef", ".notdef", ".notdef",
  381.     ".notdef", ".notdef", ".notdef", ".notdef",
  382.     ".notdef", ".notdef", ".notdef", ".notdef",
  383.     ".notdef", ".notdef", ".notdef", ".notdef",
  384.     ".notdef", "AE", ".notdef", "ordfeminine",
  385.     ".notdef", ".notdef", ".notdef", ".notdef",
  386.     "Lslash", "Oslash", "OE", "ordmasculine",
  387.     ".notdef", ".notdef", ".notdef", ".notdef",
  388.     ".notdef", "ae", ".notdef", ".notdef",
  389.     ".notdef", "dotlessi", ".notdef", ".notdef",
  390.     "lslash", "oslash", "oe", "germandbls",
  391.     ".notdef", ".notdef", ".notdef", ".notdef"
  392. };
  393.  
  394. /*
  395.  * Decription of the supported conversions from Unicode
  396.  *
  397.  * SB
  398.  * Yes, I know that the compiled-in conversion is stupid but
  399.  * it is simple to implement and allows not to worry about the
  400.  * filesystem context. After all, the source is always available
  401.  * and adding another language to it is easy.
  402.  *
  403.  * The language name is expected to be the same as the subdirectory name 
  404.  * in the `encodings' directory (for possible future extensions). 
  405.  * The primary use of the aliases is for guessing based on the current 
  406.  * locale.
  407.  */
  408.  
  409. #define MAXUNIALIAS 10
  410. #define MAXUNITABLES 3
  411.  
  412. /* the character used as the language argument separator */
  413. #define LANG_ARG_SEP '+'
  414.  
  415.  
  416. /*
  417.  * Types of language-related routines. Arguments are:
  418.  * name is the glyph name
  419.  * arg is the user-specified language-dependent argument
  420.  *   which can for example select the subfont plane for Eastern fonts.
  421.  *   If none is supplied by user then an empty string ("") is passed.
  422.  *   If no language is specified by user and auto-guessing happens
  423.  *   then NULL is passed.
  424.  * when shows if the conversion by name was called before conversion by
  425.  *   map or after (it's called twice)
  426.  */
  427.  
  428. /* type of the Unicode map initialization routine */
  429. typedef void uni_init_t(char *arg);
  430.  
  431. /* type of Unicode converter-by-name function
  432.  * it's called for each glyph twice: one time for each glyph
  433.  * before doing conversion by map and one time after
  434.  */
  435. typedef int uni_conv_t(char *name, char *arg, int when);
  436. #define UNICONV_BYNAME_BEFORE 0
  437. #define UNICONV_BYNAME_AFTER 1
  438.  
  439. struct uni_language {
  440.     uni_init_t    *init[MAXUNITABLES]; /* map initialization routines */
  441.     uni_conv_t    *convbyname; /* the name-based conversion function */
  442.     char *name; /* the language name */
  443.     char *descr; /* description */
  444.     char *alias[MAXUNIALIAS]; /* aliases of the language name */
  445.     int sample_upper; /* code of some uppercase character for correctvsize() */
  446. };
  447.  
  448. /* the converter routines have an option of adding this suffix to the font name */
  449. static char *uni_font_name_suffix = ""; /* empty by default */
  450. /* this buffer may be used to store the suffix */
  451. #define UNI_MAX_SUFFIX_LEN    100
  452. static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
  453.  
  454. /*
  455.  * Prototypes of the conversion routines
  456.  */
  457.  
  458. static uni_init_t unicode_latin1;
  459. static uni_init_t unicode_latin2;
  460. static uni_init_t unicode_latin4;
  461. static uni_init_t unicode_latin5;
  462. static uni_init_t unicode_cyrillic;
  463. static uni_init_t unicode_adobestd;
  464. static uni_init_t unicode_plane;
  465. static uni_conv_t unicode_adobestd_byname;
  466.  
  467. static uni_init_t unicode_init_user;
  468.  
  469. /*
  470.  * The order of descriptions is important: if we can't guess the
  471.  * language we just call all the conversion routines in order until
  472.  * we find one that understands this glyph.
  473.  */
  474. static struct uni_language uni_lang[]= {
  475.     /* pseudo-language for all the languages using Latin1 */
  476.     {
  477.         { unicode_latin1 },
  478.         0, /* no name-based mapping */
  479.         "latin1",
  480.         "works for most of the Western languages",
  481.         { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
  482.         'A'
  483.     },
  484.     { /* by Szalay Tamas <tomek@elender.hu> */
  485.         { unicode_latin2 },
  486.         0, /* no name-based mapping */
  487.         "latin2",
  488.         "works for Central European languages",
  489.         { "hu_","pl_","cz_","si_","sk_" },
  490.         'A'
  491.     },
  492.     { /* by Rièardas Èepas <rch@WriteMe.Com> */
  493.         { unicode_latin4 }, 
  494.         0, /* no name-based mapping */
  495.         "latin4",
  496.         "works for Baltic languages",
  497.         { "lt_", "lv_" }, /* doubt about ee_ */
  498.         'A'
  499.     },
  500.     { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
  501.         { unicode_latin5 }, 
  502.         0, /* no name-based mapping */
  503.         "latin5",
  504.         "for Turkish",
  505.         { "tr_" },
  506.         'A'
  507.     },
  508.     { /* by Zvezdan Petkovic <z.petkovic@computer.org> */
  509.         { unicode_cyrillic, unicode_latin1 },
  510.         0, /* no name-based mapping */
  511.         "cyrillic",
  512.         "in Windows encoding",
  513.         { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
  514.         'A'
  515.     },
  516.     {
  517.         { unicode_cyrillic, unicode_latin1 },
  518.         0, /* no name-based mapping */
  519.         "russian",
  520.         "obsolete, use cyrillic instead",
  521.         { 0 },
  522.         'A'
  523.     },
  524.     {
  525.         { unicode_cyrillic, unicode_latin1 },
  526.         0, /* no name-based mapping */
  527.         "bulgarian",
  528.         "obsolete, use cyrillic instead",
  529.         { 0 },
  530.         'A'
  531.     },
  532.     {
  533.         { unicode_adobestd },
  534.         unicode_adobestd_byname,
  535.         "adobestd",
  536.         "Adobe Standard, expected by TeX",
  537.         { NULL },
  538.         'A'
  539.     },
  540.     {
  541.         { unicode_plane },
  542.         0, /* no name-based mapping */
  543.         "plane",
  544.         "one plane of Unicode or other multi-byte encoding as is",
  545.         { NULL },
  546.         0 /* no easy way to predict the capital letters */
  547.     },
  548. };
  549.  
  550. static struct uni_language uni_lang_user = {
  551.     { unicode_init_user }, 
  552.     0, /* no name-based mapping */
  553.     0, /* no name */
  554.     0, /* no description */
  555.     { 0 },
  556.     0 /* no sample */
  557. };
  558.  
  559. static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
  560. static int uni_sample='A'; /* sample of an uppercase character */
  561. static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
  562.  
  563. extern int      runt1asm(int);
  564.  
  565. /*
  566.  * user-defined loadable maps
  567.  */
  568.  
  569.  
  570. /* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
  571.  * All the 16-bit unicode space is divided between a number of equal-sized buckets.
  572.  * Initially all the buckets are marked with 0. Then if any code in the bucket is
  573.  * used it's marked with 1. Later during translation we check the code's bucket first
  574.  * and it it's 0 then return failure right away. This may be useful for
  575.  * Chinese fonts with many thousands of glyphs.
  576.  */
  577.  
  578. #define BUCKET_ID_BITS    11
  579. #define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
  580. #define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
  581.  
  582. static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
  583.  
  584. static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
  585. static int enctabsz = 256; /* actual number of codes used */
  586.  
  587. static void
  588. unicode_init_user(
  589.          char *path
  590. )
  591. {
  592.     FILE           *unicode_map_file;
  593. #define UNIBFSZ    256
  594.     char            buffer[UNIBFSZ];
  595.     unsigned        code, unicode, curpos, unicode2;
  596.     char           *arg, *p;
  597.     int             enabled, found, sawplane;
  598.     int             lineno, cnt, n, nchars;
  599.     char            next;
  600.     int             pid, eid, overid=0;
  601.  
  602.     /* check if we have an argument (plane name) */
  603.     arg = strrchr(path, LANG_ARG_SEP);
  604.     if(arg != 0) {
  605.         *arg++ = 0;
  606.         if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
  607.             force_pid = pid; force_eid = eid; overid = 1;
  608.             WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
  609.             forcemap = 1;
  610.             arg += nchars;
  611.             if(*arg == ',')
  612.                 arg++;
  613.         }
  614.         if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1) 
  615.             arg = NULL;
  616.         else {
  617.             sprintf(uni_suffix_buf, "-%s", arg);
  618.             uni_font_name_suffix = uni_suffix_buf;
  619.         }
  620.     } 
  621.  
  622.     /* now read in the encoding description file, if requested */
  623.     if ((unicode_map_file = fopen(path, "r")) == NULL) {
  624.         fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
  625.         exit(1);
  626.     }
  627.  
  628.     sawplane = 0;
  629.     if(arg==NULL)
  630.         enabled = found = 1;
  631.     else
  632.         enabled = found = 0;
  633.  
  634.     lineno=0; curpos=0;
  635.     while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
  636.         char name[UNIBFSZ];
  637.  
  638.         lineno++;
  639.  
  640.         if(sscanf(buffer, "plane %s", name)==1) {
  641.             sawplane = 1;
  642.             if(arg == 0) {
  643.                 fprintf(stderr, "**** map file '%s' requires plane name\n", path);
  644.                 fprintf(stderr, "for example:\n");
  645.                 fprintf(stderr, "  ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n", 
  646.                     path, LANG_ARG_SEP, name);
  647.                 fprintf(stderr, "to select plane '%s'\n", name);
  648.                 exit(1);
  649.             }
  650.             if( !strcmp(arg, name) ) {
  651.                 enabled = found = 1; 
  652.                 curpos = 0;
  653.             } else {
  654.                 enabled = 0;
  655.                 if(found) /* no need to read further */
  656.                     break;
  657.             }
  658.             continue;
  659.         }
  660.  
  661.         if(sscanf(buffer, "id %d %d", pid, eid)==2) {
  662.             if( !overid /* only if the user has not overriden */
  663.             && (enabled || !sawplane) ) { 
  664.                 force_pid = pid; force_eid = eid;
  665.                 forcemap = 1;
  666.             }
  667.             continue;
  668.         }
  669.  
  670.         if( !enabled )
  671.             continue; /* skip to the next plane */
  672.  
  673.         if( sscanf(buffer, "at %i", &curpos) == 1 ) {
  674.             if(curpos > 255) {
  675.                 fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
  676.                 exit(1);
  677.             }
  678.             if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
  679.             continue;
  680.         }
  681.  
  682.         /* try the format of Roman Czyborra's files */
  683.         if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
  684.         /* try the format of Linux locale charmap file */
  685.         || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
  686.             if (code < ENCTABSZ) {
  687.                 if(code >= enctabsz) enctabsz=code+1;
  688.                 unicode_map[code] = unicode;
  689.                 glyph_rename[code] = NULL;
  690.             }
  691.         }
  692.         /* try the format with glyph renaming */
  693.         else if (sscanf (buffer, " !%x U+%4x %128s", &code,
  694.             &unicode, name) == 3) {
  695.             if (code < ENCTABSZ) {
  696.                 if(code >= enctabsz) enctabsz=code+1;
  697.                 unicode_map[code] = unicode;
  698.                 glyph_rename[code] = strdup(name);
  699.             }
  700.         }
  701.         /* try the compact sequence format */
  702.         else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
  703.             p = buffer;
  704.             do {
  705.                 if(curpos > 255) {
  706.                     fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n", 
  707.                         path, lineno, unicode);
  708.                     exit(1);
  709.                 }
  710.                 if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
  711.                 unicode_map[curpos++] = unicode;
  712.                 p += cnt;
  713.                 if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
  714.                     if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
  715.                     p += cnt;
  716.                     if( next == '-' ) { /* range */
  717.                         if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
  718.                             fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
  719.                             exit(1);
  720.                         }
  721.                         p += cnt;
  722.                         if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
  723.                         for(unicode++; unicode <= unicode2; unicode++) {
  724.                             if(curpos > 255) {
  725.                                 fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n", 
  726.                                     path, lineno, unicode2);
  727.                                 exit(1);
  728.                             }
  729.                             if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
  730.                             unicode_map[curpos++] = unicode;
  731.                         }
  732.                     }
  733.                 }
  734.             } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
  735.         }
  736.  
  737.     }
  738.  
  739.     fclose (unicode_map_file);
  740.  
  741.     if( !found ) {
  742.         fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
  743.         exit(1);
  744.     }
  745.  
  746.     if(unicode_map['A'] == 'A')
  747.         uni_sample = 'A'; /* seems to be compatible with Latin */
  748.     else
  749.         uni_sample = 0; /* don't make any assumptions */
  750. }
  751.  
  752. /*
  753.  * by Zvezdan Petkovic <z.petkovic@computer.org> 
  754.  */
  755. static void
  756. unicode_cyrillic(
  757.          char *arg
  758. )
  759. {
  760.     int i;
  761.     static unsigned int cyrillic_unicode_map[] = {
  762.         0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
  763.         0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,  /* 88 */
  764.         0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
  765.         0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,  /* 98 */
  766.         0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,  /* A0 */
  767.         0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,  /* A8 */
  768.         0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,  /* B0 */
  769.         0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,  /* B8 */
  770.     };
  771.  
  772.     for(i=0; i<=0x7F; i++)
  773.         unicode_map[i] = i;
  774.  
  775.     for(i=0x80; i<=0xBF; i++)
  776.         unicode_map[i] = cyrillic_unicode_map[i-0x80];
  777.  
  778.     for(i=0xC0; i<=0xFF; i++)
  779.         unicode_map[i] = i+0x350;
  780.  
  781. }
  782.  
  783. static void
  784. unicode_latin1(
  785.          char *arg
  786. )
  787. {
  788.     int i;
  789.     static unsigned int latin1_unicode_map[] = {
  790.         0x20ac,     -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
  791.         0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,  /* 88 */
  792.         0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
  793.         0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,  /* 98 */
  794.     };
  795.  
  796.     for(i=0; i<=0x7F; i++)
  797.         unicode_map[i] = i;
  798.  
  799.     for(i=0x80; i<=0x9F; i++)
  800.         unicode_map[i] = latin1_unicode_map[i-0x80];
  801.  
  802.     for(i=0xA0; i<=0xFF; i++)
  803.         unicode_map[i] = i;
  804. }
  805.  
  806. static void
  807. unicode_adobestd(
  808.          char *arg
  809. )
  810. {
  811.     int i;
  812.     static unsigned int adobestd_unicode_map[] = {
  813.             -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7,  /* A0 */
  814.         0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02,  /* A8 */
  815.             -1, 0x2013, 0x2020, 0x2021, 0x2219,     -1, 0x00b6, 0x2022,  /* B0 */
  816.         0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030,     -1, 0x00bf,  /* B8 */
  817.             -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9,  /* C0 */
  818.         0x00a8,     -1, 0x02da, 0x00b8,     -1, 0x02dd, 0x02db, 0x02c7,  /* C8 */
  819.         0x2014,     -1,     -1,     -1,     -1,     -1,     -1,     -1,  /* D0 */
  820.             -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,  /* D8 */
  821.             -1, 0x00c6,     -1, 0x00aa,     -1,     -1,     -1,     -1,  /* E0 */
  822.         0x0141, 0x00d8, 0x0152, 0x00ba,     -1,     -1,     -1,     -1,  /* E8 */
  823.             -1, 0x00e6,     -1,     -1,     -1, 0x0131,     -1,     -1,  /* F0 */
  824.         0x0142, 0x00f8, 0x0153, 0x00df,     -1,     -1,     -1,     -1,  /* F8 */
  825.     };
  826.  
  827.     for(i=0; i<=0x7F; i++)
  828.         unicode_map[i] = i;
  829.  
  830.     unicode_map[0x27] = 0x2019;
  831.     unicode_map[0x60] = -1;
  832.  
  833.     /* 0x80 to 0x9F is a hole */
  834.  
  835.     for(i=0xA0; i<=0xFF; i++)
  836.         unicode_map[i] = adobestd_unicode_map[i-0xA0];
  837. }
  838.  
  839. /*
  840.  * Not all of the Adobe glyphs are in the Unicode
  841.  * standard maps, so the font creators have
  842.  * different ideas about their codes. Because
  843.  * of this we try to map based on the glyph
  844.  * names instead of Unicode codes. If there are
  845.  * no glyph names (ps_fmt_3!=0) we fall back
  846.  * to the code-based scheme.
  847.  */
  848.  
  849. static int
  850. unicode_adobestd_byname(
  851.          char *name,
  852.          char *arg,
  853.          int where
  854. )
  855. {
  856.     int i;
  857.  
  858.     /* names always take precedence over codes */
  859.     if(where == UNICONV_BYNAME_AFTER)
  860.         return -1;
  861.  
  862.     for(i=32; i<256; i++) {
  863.         if(!strcmp(name, adobe_StandardEncoding[i]))
  864.             return i;
  865.     }
  866.     return -1;
  867.  
  868. }
  869.  
  870. static void
  871. unicode_latin2(
  872.          char *arg
  873. )
  874. {
  875.     int i;
  876.     static unsigned int latin2_unicode_map[] = {
  877.         0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,  /* A0 */
  878.         0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,  /* A8 */
  879.         0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,  /* B0 */
  880.         0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,  /* B8 */
  881.         0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,  /* C0 */
  882.         0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,  /* C8 */
  883.         0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,  /* D0 */
  884.         0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,  /* D8 */
  885.         0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,  /* E0 */
  886.         0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,  /* E8 */
  887.         0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,  /* F0 */
  888.         0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,  /* F8 */
  889.     };
  890.  
  891.     for(i=0; i<=0x7E; i++)
  892.         unicode_map[i] = i;
  893.  
  894.     /* 7F-9F are unused */
  895.  
  896.     for(i=0xA0; i<=0xFF; i++)
  897.         unicode_map[i] = latin2_unicode_map[i-0xA0];
  898. }
  899.  
  900. static void
  901. unicode_latin4(
  902.          char *arg
  903. )
  904. {
  905.     int i;
  906.     static unsigned int latin4_unicode_map[] = {
  907.         0x0080, 0x0081, 0x201a, 0x0192,     -1, 0x2026, 0x2020, 0x2021,  /* 80 */
  908.         0x02c6, 0x2030,     -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,  /* 88 */
  909.         0x201e, 0x201c, 0x2019,     -1, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
  910.         0x02dc, 0x2122,     -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,  /* 98 */
  911.         0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7,  /* A0 */
  912.         0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af,  /* A8 */
  913.         0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7,  /* B0 */
  914.         0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b,  /* B8 */
  915.         0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e,  /* C0 */
  916.         0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a,  /* C8 */
  917.         0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7,  /* D0 */
  918.         0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df,  /* D8 */
  919.         0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f,  /* E0 */
  920.         0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b,  /* E8 */
  921.         0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7,  /* F0 */
  922.         0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9,  /* F8 */
  923.     };
  924.  
  925.     for(i=0; i<=0x7F; i++)
  926.         unicode_map[i] = i;
  927.  
  928.     for(i=0x80; i<=0xFF; i++)
  929.         unicode_map[i] = latin4_unicode_map[i-0x80];
  930.  
  931. #if 0 /* for documentation purposes only */
  932.     case 0x201e: return 0x90; /* these two quotes are a hack only */
  933.     case 0x201c: return 0x91; /* these two quotes are a hack only */
  934.     case 0x00A0: return 0xA0; /*  NO-BREAK SPACE */
  935.     case 0x0104: return 0xA1; /*  LATIN CAPITAL LETTER A WITH OGONEK */
  936.     case 0x0138: return 0xA2; /*  LATIN SMALL LETTER KRA */
  937.     case 0x0156: return 0xA3; /*  LATIN CAPITAL LETTER R WITH CEDILLA */
  938.     case 0x00A4: return 0xA4; /*  CURRENCY SIGN */
  939.     case 0x0128: return 0xA5; /*  LATIN CAPITAL LETTER I WITH TILDE */
  940.     case 0x013B: return 0xA6; /*  LATIN CAPITAL LETTER L WITH CEDILLA */
  941.     case 0x00A7: return 0xA7; /*  SECTION SIGN */
  942.     case 0x00A8: return 0xA8; /*  DIAERESIS */
  943.     case 0x0160: return 0xA9; /*  LATIN CAPITAL LETTER S WITH CARON */
  944.     case 0x0112: return 0xAA; /*  LATIN CAPITAL LETTER E WITH MACRON */
  945.     case 0x0122: return 0xAB; /*  LATIN CAPITAL LETTER G WITH CEDILLA */
  946.     case 0x0166: return 0xAC; /*  LATIN CAPITAL LETTER T WITH STROKE */
  947.     case 0x00AD: return 0xAD; /*  SOFT HYPHEN */
  948.     case 0x017D: return 0xAE; /*  LATIN CAPITAL LETTER Z WITH CARON */
  949.     case 0x00AF: return 0xAF; /*  MACRON */
  950.     case 0x00B0: return 0xB0; /*  DEGREE SIGN */
  951.     case 0x0105: return 0xB1; /*  LATIN SMALL LETTER A WITH OGONEK */
  952.     case 0x02DB: return 0xB2; /*  OGONEK */
  953.     case 0x0157: return 0xB3; /*  LATIN SMALL LETTER R WITH CEDILLA */
  954.     case 0x00B4: return 0xB4; /*  ACUTE ACCENT */
  955.     case 0x0129: return 0xB5; /*  LATIN SMALL LETTER I WITH TILDE */
  956.     case 0x013C: return 0xB6; /*  LATIN SMALL LETTER L WITH CEDILLA */
  957.     case 0x02C7: return 0xB7; /*  CARON */
  958.     case 0x00B8: return 0xB8; /*  CEDILLA */
  959.     case 0x0161: return 0xB9; /*  LATIN SMALL LETTER S WITH CARON */
  960.     case 0x0113: return 0xBA; /*  LATIN SMALL LETTER E WITH MACRON */
  961.     case 0x0123: return 0xBB; /*  LATIN SMALL LETTER G WITH CEDILLA */
  962.     case 0x0167: return 0xBC; /*  LATIN SMALL LETTER T WITH STROKE */
  963.     case 0x014A: return 0xBD; /*  LATIN CAPITAL LETTER ENG */
  964.     case 0x017E: return 0xBE; /*  LATIN SMALL LETTER Z WITH CARON */
  965.     case 0x014B: return 0xBF; /*  LATIN SMALL LETTER ENG */
  966.     case 0x0100: return 0xC0; /*  LATIN CAPITAL LETTER A WITH MACRON */
  967.     case 0x00C1: return 0xC1; /*  LATIN CAPITAL LETTER A WITH ACUTE */
  968.     case 0x00C2: return 0xC2; /*  LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
  969.     case 0x00C3: return 0xC3; /*  LATIN CAPITAL LETTER A WITH TILDE */
  970.     case 0x00C4: return 0xC4; /*  LATIN CAPITAL LETTER A WITH DIAERESIS */
  971.     case 0x00C5: return 0xC5; /*  LATIN CAPITAL LETTER A WITH RING ABOVE */
  972.     case 0x00C6: return 0xC6; /*  LATIN CAPITAL LIGATURE AE */
  973.     case 0x012E: return 0xC7; /*  LATIN CAPITAL LETTER I WITH OGONEK */
  974.     case 0x010C: return 0xC8; /*  LATIN CAPITAL LETTER C WITH CARON */
  975.     case 0x00C9: return 0xC9; /*  LATIN CAPITAL LETTER E WITH ACUTE */
  976.     case 0x0118: return 0xCA; /*  LATIN CAPITAL LETTER E WITH OGONEK */
  977.     case 0x00CB: return 0xCB; /*  LATIN CAPITAL LETTER E WITH DIAERESIS */
  978.     case 0x0116: return 0xCC; /*  LATIN CAPITAL LETTER E WITH DOT ABOVE */
  979.     case 0x00CD: return 0xCD; /*  LATIN CAPITAL LETTER I WITH ACUTE */
  980.     case 0x00CE: return 0xCE; /*  LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
  981.     case 0x012A: return 0xCF; /*  LATIN CAPITAL LETTER I WITH MACRON */
  982.     case 0x0110: return 0xD0; /*  LATIN CAPITAL LETTER D WITH STROKE */
  983.     case 0x0145: return 0xD1; /*  LATIN CAPITAL LETTER N WITH CEDILLA */
  984.     case 0x014C: return 0xD2; /*  LATIN CAPITAL LETTER O WITH MACRON */
  985.     case 0x0136: return 0xD3; /*  LATIN CAPITAL LETTER K WITH CEDILLA */
  986.     case 0x00D4: return 0xD4; /*  LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
  987.     case 0x00D5: return 0xD5; /*  LATIN CAPITAL LETTER O WITH TILDE */
  988.     case 0x00D6: return 0xD6; /*  LATIN CAPITAL LETTER O WITH DIAERESIS */
  989.     case 0x00D7: return 0xD7; /*  MULTIPLICATION SIGN */
  990.     case 0x00D8: return 0xD8; /*  LATIN CAPITAL LETTER O WITH STROKE */
  991.     case 0x0172: return 0xD9; /*  LATIN CAPITAL LETTER U WITH OGONEK */
  992.     case 0x00DA: return 0xDA; /*  LATIN CAPITAL LETTER U WITH ACUTE */
  993.     case 0x00DB: return 0xDB; /*  LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
  994.     case 0x00DC: return 0xDC; /*  LATIN CAPITAL LETTER U WITH DIAERESIS */
  995.     case 0x0168: return 0xDD; /*  LATIN CAPITAL LETTER U WITH TILDE */
  996.     case 0x016A: return 0xDE; /*  LATIN CAPITAL LETTER U WITH MACRON */
  997.     case 0x00DF: return 0xDF; /*  LATIN SMALL LETTER SHARP S */
  998.     case 0x0101: return 0xE0; /*  LATIN SMALL LETTER A WITH MACRON */
  999.     case 0x00E1: return 0xE1; /*  LATIN SMALL LETTER A WITH ACUTE */
  1000.     case 0x00E2: return 0xE2; /*  LATIN SMALL LETTER A WITH CIRCUMFLEX */
  1001.     case 0x00E3: return 0xE3; /*  LATIN SMALL LETTER A WITH TILDE */
  1002.     case 0x00E4: return 0xE4; /*  LATIN SMALL LETTER A WITH DIAERESIS */
  1003.     case 0x00E5: return 0xE5; /*  LATIN SMALL LETTER A WITH RING ABOVE */
  1004.     case 0x00E6: return 0xE6; /*  LATIN SMALL LIGATURE AE */
  1005.     case 0x012F: return 0xE7; /*  LATIN SMALL LETTER I WITH OGONEK */
  1006.     case 0x010D: return 0xE8; /*  LATIN SMALL LETTER C WITH CARON */
  1007.     case 0x00E9: return 0xE9; /*  LATIN SMALL LETTER E WITH ACUTE */
  1008.     case 0x0119: return 0xEA; /*  LATIN SMALL LETTER E WITH OGONEK */
  1009.     case 0x00EB: return 0xEB; /*  LATIN SMALL LETTER E WITH DIAERESIS */
  1010.     case 0x0117: return 0xEC; /*  LATIN SMALL LETTER E WITH DOT ABOVE */
  1011.     case 0x00ED: return 0xED; /*  LATIN SMALL LETTER I WITH ACUTE */
  1012.     case 0x00EE: return 0xEE; /*  LATIN SMALL LETTER I WITH CIRCUMFLEX */
  1013.     case 0x012B: return 0xEF; /*  LATIN SMALL LETTER I WITH MACRON */
  1014.     case 0x0111: return 0xF0; /*  LATIN SMALL LETTER D WITH STROKE */
  1015.     case 0x0146: return 0xF1; /*  LATIN SMALL LETTER N WITH CEDILLA */
  1016.     case 0x014D: return 0xF2; /*  LATIN SMALL LETTER O WITH MACRON */
  1017.     case 0x0137: return 0xF3; /*  LATIN SMALL LETTER K WITH CEDILLA */
  1018.     case 0x00F4: return 0xF4; /*  LATIN SMALL LETTER O WITH CIRCUMFLEX */
  1019.     case 0x00F5: return 0xF5; /*  LATIN SMALL LETTER O WITH TILDE */
  1020.     case 0x00F6: return 0xF6; /*  LATIN SMALL LETTER O WITH DIAERESIS */
  1021.     case 0x00F7: return 0xF7; /*  DIVISION SIGN */
  1022.     case 0x00F8: return 0xF8; /*  LATIN SMALL LETTER O WITH STROKE */
  1023.     case 0x0173: return 0xF9; /*  LATIN SMALL LETTER U WITH OGONEK */
  1024.     case 0x00FA: return 0xFA; /*  LATIN SMALL LETTER U WITH ACUTE */
  1025.     case 0x00FB: return 0xFB; /*  LATIN SMALL LETTER U WITH CIRCUMFLEX */
  1026.     case 0x00FC: return 0xFC; /*  LATIN SMALL LETTER U WITH DIAERESIS */
  1027.     case 0x0169: return 0xFD; /*  LATIN SMALL LETTER U WITH TILDE */
  1028.     case 0x016B: return 0xFE; /*  LATIN SMALL LETTER U WITH MACRON */
  1029.     case 0x02D9: return 0xFF; /*  DOT ABOVE */
  1030. #endif
  1031. }
  1032.  
  1033. static void
  1034. unicode_latin5(
  1035.          char *arg
  1036. )
  1037. {
  1038.     int i;
  1039.     static unsigned int latin5_unicode_map1[] = {
  1040.         0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
  1041.         0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,  /* 88 */
  1042.         0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
  1043.         0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,  /* 98 */
  1044.     };
  1045.     static unsigned int latin5_unicode_map2[] = {
  1046.         0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,  /* D0 */
  1047.         0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,  /* D8 */
  1048.         0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,  /* E0 direct */
  1049.         0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,  /* E8 direct */
  1050.         0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,  /* F0 */
  1051.         0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff,  /* F8 */
  1052.     };
  1053.  
  1054.     for(i=0; i<=0x7F; i++)
  1055.         unicode_map[i] = i;
  1056.  
  1057.     for(i=0x80; i<=0x9F; i++)
  1058.         unicode_map[i] = latin5_unicode_map1[i-0x80];
  1059.  
  1060.     for(i=0xA0; i<=0xCF; i++)
  1061.         unicode_map[i] = i;
  1062.  
  1063.     for(i=0xD0; i<=0xFF; i++)
  1064.         unicode_map[i] = latin5_unicode_map2[i-0xD0];
  1065. }
  1066.  
  1067. /* a way to select one 256-character plane from Unicode 
  1068.  * or other multi-byte encoding
  1069.  */
  1070.  
  1071. static void
  1072. unicode_plane(
  1073.          char *arg
  1074. )
  1075. {
  1076.     static unsigned plane;
  1077.     int nchars;
  1078.     int c1, c2, i;
  1079.  
  1080.     if(uni_lang_selected == 0)
  1081.         return; /* don't participate in auto-guessing */
  1082.  
  1083.     plane = 0; force_pid = force_eid = -1;
  1084.  
  1085.     c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
  1086.     if(c1 == 2) {
  1087.         arg += nchars;
  1088.         if(*arg == ',')
  1089.             arg++;
  1090.     }
  1091.     if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
  1092.         arg += 2;
  1093.         c2 = sscanf(arg, "%x", &plane);
  1094.     } else {
  1095.         c2 = sscanf(arg, "%d", &plane);
  1096.     }
  1097.  
  1098.     if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
  1099.         fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
  1100.         fprintf(stderr, "  -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
  1101.         fprintf(stderr, "  -l plane+NN - select decimal number of plane of Unicode\n");
  1102.         fprintf(stderr, "  -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
  1103.         fprintf(stderr, "  -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
  1104.         fprintf(stderr, "  -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
  1105.         exit(1);
  1106.     }
  1107.  
  1108.     if(c2!=0) {
  1109.         if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
  1110.             fprintf(stderr, "**** plane number is too large\n");
  1111.         }
  1112.  
  1113.         sprintf(uni_suffix_buf, "-%s", arg);
  1114.         uni_font_name_suffix = uni_suffix_buf;
  1115.     } else {
  1116.         uni_font_name_suffix = "";
  1117.     }
  1118.  
  1119.     plane <<= 8;
  1120.     for(i=0; i<=0xFF; i++)
  1121.         unicode_map[i] = plane | i;
  1122. }
  1123.  
  1124. /* look up the 8-bit code by unicode */
  1125.  
  1126. int
  1127. unicode_rev_lookup(
  1128.          int unival
  1129. )
  1130. {
  1131.     int res;
  1132.  
  1133.     if( ! IS_UNI_BUCKET(unival) )
  1134.         return -1;
  1135.  
  1136.     for (res = 0; res < enctabsz; res++)
  1137.         if (unicode_map[res] == unival)
  1138.             return res;
  1139.     return -1;
  1140. }
  1141.  
  1142. /* mark the buckets for quick lookup */
  1143.  
  1144. static void
  1145. unicode_prepare_buckets(
  1146.     void
  1147. )
  1148. {
  1149.     int i;
  1150.  
  1151.     memset(uni_user_buckets, 0, sizeof uni_user_buckets);
  1152.     for(i=0; i<enctabsz; i++) {
  1153.         if(unicode_map[i] != (unsigned) -1)
  1154.             MARK_UNI_BUCKET(unicode_map[i]);
  1155.     }
  1156. }
  1157.  
  1158. /*
  1159.  * Scale the values according to the scale_factor
  1160.  */
  1161.  
  1162. double
  1163. fscale(
  1164.       double val
  1165. )
  1166. {
  1167.     return scale_factor * val;
  1168. }
  1169.  
  1170. int
  1171. iscale(
  1172.       int val
  1173. )
  1174. {
  1175.     return (int) (val > 0 ? scale_factor * val + 0.5
  1176.               : scale_factor * val - 0.5);
  1177. }
  1178.  
  1179. /*
  1180.  * Try to force fixed width of characters
  1181.  */
  1182.  
  1183. static void
  1184. alignwidths(void)
  1185. {
  1186.     int             i;
  1187.     int             n = 0, avg, max = 0, min = 3000, sum = 0, x;
  1188.  
  1189.     for (i = 0; i < numglyphs; i++) {
  1190.         if (glyph_list[i].flags & GF_USED) {
  1191.             x = glyph_list[i].width;
  1192.  
  1193.             if (x != 0) {
  1194.                 if (x < min)
  1195.                     min = x;
  1196.                 if (x > max)
  1197.                     max = x;
  1198.  
  1199.                 sum += x;
  1200.                 n++;
  1201.             }
  1202.         }
  1203.     }
  1204.  
  1205.     if (n == 0)
  1206.         return;
  1207.  
  1208.     avg = sum / n;
  1209.  
  1210.     WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
  1211.  
  1212.     /* if less than 5% variation from average */
  1213.     /* force fixed width */
  1214.     if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
  1215.         for (i = 0; i < numglyphs; i++) {
  1216.             if (glyph_list[i].flags & GF_USED)
  1217.                 glyph_list[i].width = avg;
  1218.         }
  1219.         fontm.is_fixed_pitch = 1;
  1220.     }
  1221. }
  1222.  
  1223. static void
  1224. convert_glyf(
  1225.     int    glyphno
  1226. )
  1227. {
  1228.     GLYPH          *g;
  1229.     int ncurves;
  1230.  
  1231.     g = &glyph_list[glyphno];
  1232.  
  1233.  
  1234.     g->scaledwidth = iscale(g->width);
  1235.  
  1236.     g->entries = 0;
  1237.     g->lastentry = 0;
  1238.     g->path = 0;
  1239.     if (g->ttf_pathlen != 0) {
  1240.         cursw->glpath(glyphno, glyph_list);
  1241.         g->lastentry = 0;
  1242.  
  1243.         if(ISDBG(BUILDG))
  1244.             dumppaths(g, NULL, NULL);
  1245.  
  1246.         assertpath(g->entries, __FILE__, __LINE__, g->name);
  1247.  
  1248.         fclosepaths(g);
  1249.         assertpath(g->entries, __FILE__, __LINE__, g->name);
  1250.  
  1251.         /* float processing */
  1252.         if(smooth) {
  1253.             ffixquadrants(g);
  1254.             assertpath(g->entries, __FILE__, __LINE__, g->name);
  1255.  
  1256.             fsplitzigzags(g);
  1257.             assertpath(g->entries, __FILE__, __LINE__, g->name);
  1258.  
  1259.             fforceconcise(g);
  1260.             assertpath(g->entries, __FILE__, __LINE__, g->name);
  1261.  
  1262.             fstraighten(g);
  1263.             assertpath(g->entries, __FILE__, __LINE__, g->name);
  1264.         }
  1265.  
  1266.         pathtoint(g); 
  1267.         /* all processing past this point expects integer path */
  1268.         assertpath(g->entries, __FILE__, __LINE__, g->name);
  1269.  
  1270. #if 0
  1271.         fixcontours(g);
  1272.         testfixcvdir(g);
  1273. #endif
  1274.  
  1275.         /* int processing */
  1276.         if (smooth) {
  1277.             smoothjoints(g);
  1278.             assertpath(g->entries, __FILE__, __LINE__, g->name);
  1279.  
  1280.             flattencurves(g);
  1281.         }
  1282.  
  1283.         ncurves = 0;
  1284.         {
  1285.             GENTRY *ge;
  1286.             for(ge = g->entries; ge; ge = ge->next)
  1287.                 ncurves++;
  1288.         }
  1289.         if (ncurves > 100) {
  1290.             WARNING_2 fprintf(stderr,
  1291.             "** Glyph %s is too long, may display incorrectly\n",
  1292.                 g->name);
  1293.         }
  1294.     } else {
  1295.         /* for buildstems */
  1296.         g->flags &= ~GF_FLOAT;
  1297.     }
  1298. }
  1299.  
  1300. static void
  1301. handle_gnames(void)
  1302. {
  1303.     int             i, n, found, c, type;
  1304.  
  1305.     /* get the names from the font file */
  1306.     ps_fmt_3 = cursw->glnames(glyph_list);
  1307.  
  1308.     /* check for names with wrong characters */
  1309.     for (n = 0; n < numglyphs; n++) {
  1310.         int             c;
  1311.         for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
  1312.             if (!(isalnum(c) || c == '.' || c == '_' ) 
  1313.             || i==0 && isdigit(c)) { /* must not start with a digit */
  1314.                 WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
  1315.                     n, isdigit(c) ? "name starts with a digit" : 
  1316.                         "has bad characters in name",
  1317.                     glyph_list[n].name);
  1318.                 glyph_list[n].name = malloc(10);
  1319.                 sprintf(glyph_list[n].name, "_%d", n);
  1320.                 WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
  1321.                 break;
  1322.             }
  1323.         }
  1324.     }
  1325.  
  1326.     if( !ps_fmt_3 ) {
  1327.         /* check for duplicate names */
  1328.         for (n = 0; n < numglyphs; n++) {
  1329.             found = 0;
  1330.             for (i = 0; i < n && !found; i++) {
  1331.                 if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
  1332.                     glyph_list[n].name = malloc(10);
  1333.                     sprintf(glyph_list[n].name, "_%d", n);
  1334.                     WARNING_3 fprintf(stderr,
  1335.                         "Glyph %d has the same name as %d: (%s), changing to %s\n",
  1336.                         n, i,
  1337.                         glyph_list[i].name,
  1338.                         glyph_list[n].name);
  1339.                     found = 1;
  1340.                 }
  1341.             }
  1342.         }
  1343.  
  1344.     }
  1345.  
  1346.     /* start the encoding stuff */
  1347.     for (i = 0; i < ENCTABSZ; i++) {
  1348.         encoding[i] = -1;
  1349.     }
  1350.  
  1351.     /* do the 1st round of encoding by name */
  1352.     if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
  1353.         for (n = 0; n < numglyphs; n++) {
  1354.             c = uni_lang_selected->convbyname(glyph_list[n].name, 
  1355.                 uni_lang_arg, UNICONV_BYNAME_BEFORE);
  1356.             if(c>=0 && c<ENCTABSZ && encoding[n] == -1)
  1357.                 encoding[n] = n;
  1358.         }
  1359.     }
  1360.  
  1361.     /* now do the encoding by table */
  1362.     if(uni_lang_selected) {
  1363.         for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
  1364.             for (n = 0; n < ENCTABSZ; n++)
  1365.                 unicode_map[n] = -1;
  1366.             uni_lang_selected->init[i](uni_lang_arg);
  1367.             unicode_prepare_buckets();
  1368.             if( cursw->glenc(glyph_list, encoding, unicode_map) == 0 )
  1369.                 /* if we have an 8-bit encoding we don't need more tries */
  1370.                 break;
  1371.         }
  1372.     } else {
  1373.         /* language is unknown, try the first table of each */
  1374.         for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
  1375.             if(uni_lang[i].init[0] == NULL)
  1376.                 continue;
  1377.             for (n = 0; n < ENCTABSZ; n++)
  1378.                 unicode_map[n] = -1;
  1379.             uni_lang[i].init[0](uni_lang_arg);
  1380.             unicode_prepare_buckets();
  1381.             if( cursw->glenc(glyph_list, encoding, unicode_map) == 0 )
  1382.                 /* if we have an 8-bit encoding we don't need more tries */
  1383.                 break;
  1384.         }
  1385.     }
  1386.  
  1387.     if (ps_fmt_3) {
  1388.         for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
  1389.             if (encoding[i] > 0) {
  1390.                 glyph_list[encoding[i]].name = Fmt3Encoding[i];
  1391.             }
  1392.         }
  1393.     }
  1394.  
  1395.     /* do the 2nd round of encoding by name */
  1396.     if(uni_lang_selected && uni_lang_selected->convbyname) {
  1397.         for (n = 0; n < numglyphs; n++) {
  1398.             c = uni_lang_selected->convbyname(glyph_list[n].name, 
  1399.                 uni_lang_arg, UNICONV_BYNAME_AFTER);
  1400.             if(c>=0 && c<ENCTABSZ && encoding[n] == -1)
  1401.                 encoding[n] = n;
  1402.         }
  1403.     }
  1404.     /* all the encoding things are done */
  1405.  
  1406.     for (i = 0; i < ENCTABSZ; i++)
  1407.         if(encoding[i] == -1) /* defaults to .notdef */
  1408.             encoding[i] = 0;
  1409.  
  1410.     for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
  1411.         glyph_list[encoding[i]].char_no = i;
  1412.  
  1413.     /* enforce two special cases defined in TTF manual */
  1414.     if(numglyphs > 0)
  1415.         glyph_list[0].name = ".notdef";
  1416.     if(numglyphs > 1)
  1417.         glyph_list[1].name = ".null";
  1418.  
  1419.      for (i = 0; i < ENCTABSZ; i++) {
  1420.          if ((encoding[i] != 0) && glyph_rename[i]) {
  1421.              glyph_list[encoding[i]].name = glyph_rename[i];
  1422.          }
  1423.      }
  1424.      
  1425. }
  1426.  
  1427. static void
  1428. usage(void)
  1429. {
  1430.  
  1431. #ifdef _GNU_SOURCE
  1432. #    define fplop(txt)    fputs(txt, stderr);
  1433. #else
  1434. #    define fplop(txt)
  1435. #endif
  1436.  
  1437.     fputs("Use:\n", stderr);
  1438.     fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
  1439.     fputs("  or\n", stderr);
  1440.     fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
  1441.     fputs("  or\n", stderr);
  1442.     fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
  1443.  
  1444.     fplop("\n");
  1445.     fplop("This build supports both short and long option names,\n");
  1446.     fplop("the long options are listed before corresponding short ones\n");
  1447.  
  1448.     fplop(" --afm\n");
  1449.     fputs("  -A - write the .afm file to STDOUT instead of the font itself\n", stderr);
  1450.     fplop(" --all-glyphs\n");
  1451.     fputs("  -a - include all glyphs, even those not in the encoding table\n", stderr);
  1452.     fplop(" --pfb\n");
  1453.     fputs("  -b - produce a compressed .pfb file\n", stderr);
  1454.     fplop(" --debug dbg_suboptions\n");
  1455.     fputs("  -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
  1456.     fplop(" --encode\n");
  1457.     fputs("  -e - produce a fully encoded .pfa file\n", stderr);
  1458.     fplop(" --force-unicode\n");
  1459.     fputs("  -F - force use of Unicode encoding even if other MS encoding detected\n", stderr); 
  1460.     fplop(" --language language\n");
  1461.     fputs("  -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
  1462.     fplop(" --language-map file\n");
  1463.     fputs("  -L file - convert Unicode according to encoding description file\n", stderr);
  1464.     fplop(" --limit <type>=<value>\n");
  1465.     fputs("  -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
  1466.     fputs("      h - maximal hint stack depth in the PostScript interpreter\n", stderr);
  1467.     fplop(" --processing suboptions\n");
  1468.     fputs("  -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
  1469.     fplop(" --parser name\n");
  1470.     fputs("  -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
  1471.     fplop(" --uid id\n");
  1472.     fputs("  -u id - use this UniqueID, -u A means autogeneration\n", stderr);
  1473.     fplop(" --vertical-autoscale size\n");
  1474.     fputs("  -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
  1475.     fplop(" --version\n");
  1476.     fputs("  -V - print ttf2pt1 version number\n", stderr);
  1477.     fplop(" --warning number\n");
  1478.     fputs("  -W number - set the level of permitted warnings (0 - disable)\n", stderr);
  1479.     fputs("Obsolete options (will be removed in future releases, use -O? instead):\n", stderr);
  1480.     fputs("  -f - don't try to guess the value of the ForceBold hint\n", stderr);
  1481.     fputs("  -h - disable autogeneration of hints\n", stderr);
  1482.     fputs("  -H - disable hint substitution\n", stderr);
  1483.     fputs("  -o - disable outline optimization\n", stderr);
  1484.     fputs("  -s - disable outline smoothing\n", stderr);
  1485.     fputs("  -t - disable auto-scaling to 1000x1000 standard matrix\n", stderr);
  1486.     fputs("  -w - correct the glyph widths (use only for buggy fonts)\n", stderr);
  1487.     fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
  1488.     fputs("The last '-' means 'use STDOUT'.\n", stderr);
  1489.  
  1490. #undef fplop
  1491.  
  1492. }
  1493.  
  1494. static void
  1495. printversion(void)
  1496. {
  1497.   fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
  1498. }
  1499.  
  1500. #ifdef AMIGA
  1501. static void
  1502. swap_stack_back(void)
  1503. {
  1504.     if( new_stack )
  1505.     {
  1506.         StackSwap( &stackswap );
  1507.         FreeVec( new_stack );
  1508.         new_stack = NULL;
  1509.     }
  1510. }
  1511. #endif
  1512.  
  1513. int
  1514. main(
  1515.      int argc,
  1516.      char **argv
  1517. )
  1518. {
  1519.     int             i, j;
  1520.     time_t          now;
  1521.     char            filename[256];
  1522.     int             c,nchars,nmetrics;
  1523.     int             ws;
  1524.     int             forcebold= -1; /* -1 means "don't know" */
  1525.     char           *lang;
  1526.     int             oc;
  1527.     int             subid;
  1528. #ifdef _GNU_SOURCE
  1529. #    define ttf2pt1_getopt(a, b, c, d, e)    getopt_long(a, b, c, d, e)
  1530.     static struct option longopts[] = {
  1531.         { "afm", 0, NULL, 'A' },
  1532.         { "all-glyphs", 0, NULL, 'a' },
  1533.         { "pfb", 0, NULL, 'b' },
  1534.         { "debug", 1, NULL, 'd' },
  1535.         { "encode", 0, NULL, 'e' },
  1536.         { "force-unicode", 0, NULL, 'F' },
  1537.         { "language", 1, NULL, 'l' },
  1538.         { "language-map", 1, NULL, 'L' },
  1539.         { "limit", 1, NULL, 'm' },
  1540.         { "processing", 1, NULL, 'O' },
  1541.         { "parser", 1, NULL, 'p' },
  1542.         { "uid", 1, NULL, 'u' },
  1543.         { "vertical-autoscale", 1, NULL, 'v' },
  1544.         { "version", 0, NULL, 'V' },
  1545.         { "warning", 1, NULL, 'W' },
  1546.         { NULL, 0, NULL, 0 }
  1547.     };
  1548. #else
  1549. #    define ttf2pt1_getopt(a, b, c, d, e)    getopt(a, b, c)
  1550. #endif
  1551.  
  1552. #ifdef AMIGA
  1553.     struct Task *myTask = FindTask( NULL );
  1554.  
  1555.     if( myTask )
  1556.     {
  1557.         if( (ULONG)(myTask->tc_SPUpper-myTask->tc_SPLower) > AMIGA_STACKSIZE )
  1558.             myTask = NULL;
  1559.     }
  1560.  
  1561.     /* Be sure to set a sufficient stack size - 100k is the minimum we allow */
  1562.     if( myTask == NULL )
  1563.     {
  1564.         new_stack = AllocVec( AMIGA_STACKSIZE, MEMF_ANY | MEMF_PUBLIC );
  1565.         if( new_stack )
  1566.         {
  1567.             stackswap.stk_Lower   = new_stack;
  1568.             stackswap.stk_Upper   = (ULONG)new_stack+AMIGA_STACKSIZE;
  1569.             stackswap.stk_Pointer = (APTR)stackswap.stk_Upper;
  1570.             StackSwap( &stackswap );
  1571.         }
  1572.         atexit( swap_stack_back );
  1573.     }
  1574. #endif
  1575.  
  1576.     /* initialize sub-options of -O */
  1577.     for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
  1578.         opotbl[i].disbl = tolower(opotbl[i].disbl);
  1579.         opotbl[i].enbl = toupper(opotbl[i].disbl);
  1580.         *(opotbl[i].valp) = opotbl[i].dflt;
  1581.     }
  1582.  
  1583.     while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:",
  1584.             longopts, NULL) )!= -1) {
  1585.         switch(oc) {
  1586.         case 'W':
  1587.             if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) {
  1588.                 fprintf(stderr, "**** warning level must be a positive number\n");
  1589.                 exit(1);
  1590.             }
  1591.             break;
  1592.         case 'F':
  1593.             forcemap = 1;
  1594.             break;
  1595.         case 'o':
  1596.             fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
  1597.             optimize = 0;
  1598.             break;
  1599.         case 'e':
  1600.             encode = 1;
  1601.             break;
  1602.         case 'b':
  1603.             encode = pfbflag = 1;
  1604.             break;
  1605.         case 'A':
  1606.             wantafm = 1;
  1607.             break;
  1608.         case 'a':
  1609.             allglyphs = 1;
  1610.             break;
  1611.         case 's':
  1612.             fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
  1613.             smooth = 0;
  1614.             break;
  1615.         case 't':
  1616.             fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
  1617.             transform = 0;
  1618.             break;
  1619.         case 'd':
  1620.             for(i=0; optarg[i]!=0; i++)
  1621.                 switch(optarg[i]) {
  1622.                 case 'a':
  1623.                     absolute = 1;
  1624.                     break;
  1625.                 case 'r':
  1626.                     reverse = 0;
  1627.                     break;
  1628.                 default:
  1629.                     if (optarg[i] != '?')
  1630.                       fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
  1631.                     fputs("The recognized debugging options are:\n", stderr);
  1632.                     fputs("  a - enable absolute coordinates\n", stderr);
  1633.                     fputs("  r - do not reverse font outlines directions\n", stderr);
  1634.                     exit(1);
  1635.                     break;
  1636.                 };
  1637.             break;
  1638.         case 'm':
  1639.         {
  1640.             char subopt;
  1641.             int val;
  1642.  
  1643.             if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
  1644.                 fprintf(stderr, "**** Misformatted maximal limit ****\n");
  1645.                 fprintf(stderr, "spaces around the equal sign are not allowed\n");
  1646.                 fprintf(stderr, "good examples: -mh=100 -m h=100\n");
  1647.                 fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
  1648.                 exit(1);
  1649.                 break;
  1650.             }
  1651.             switch(subopt) {
  1652.             case 'h':
  1653.                 max_stemdepth = val;
  1654.                 break;
  1655.             default:
  1656.                 if (subopt != '?')
  1657.                   fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
  1658.                 fputs("The recognized limit types are:\n", stderr);
  1659.                 fputs("  h - maximal hint stack depth in the PostScript interpreter\n", stderr);
  1660.                 exit(1);
  1661.                 break;
  1662.             }
  1663.             break;
  1664.         }
  1665.         case 'O':
  1666.         {
  1667.             char subopt;
  1668.             char *p;
  1669.             char dflt[20]; /* should be big enough */
  1670.             for(p=optarg; (subopt = *p) != 0; p++) {
  1671.                 for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
  1672.                     if(subopt == opotbl[i].disbl) {
  1673.                         *(opotbl[i].valp) = 0;
  1674.                         break;
  1675.                     } else if(subopt == opotbl[i].enbl) {
  1676.                         *(opotbl[i].valp) = 1;
  1677.                         break;
  1678.                     } 
  1679.                 }
  1680.                 if( i == (sizeof opotbl)/(sizeof opotbl[0]) ) { /* found no match */
  1681.                     if (subopt != '?')
  1682.                         fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", subopt);
  1683.                     fprintf(stderr,"The general form of the outline processing option is:\n");
  1684.                     fprintf(stderr,"   -O suboptions\n");
  1685.                     fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
  1686.                     fprintf(stderr,"The lowercase suboptions disable features, corresponding\n");
  1687.                     fprintf(stderr,"uppercase suboptions enable them. The supported suboptions,\n");
  1688.                     fprintf(stderr,"their default states and the features they control are:\n");
  1689.                     p = dflt;
  1690.                     for(i=0; i< (sizeof opotbl)/(sizeof opotbl[0]); i++) {
  1691.                         fprintf(stderr,"   %c/%c - [%s] %s\n", opotbl[i].disbl, opotbl[i].enbl,
  1692.                             opotbl[i].dflt ? "enabled" : "disabled", opotbl[i].descr);
  1693.                         if(opotbl[i].dflt)
  1694.                             *p++ = opotbl[i].enbl;
  1695.                         else
  1696.                             *p++ = opotbl[i].disbl;
  1697.                     }
  1698.                     *p = 0;
  1699.                     fprintf(stderr, "The default state corresponds to the option -O %s\n", dflt);
  1700.                     exit(1);
  1701.                 }
  1702.             }
  1703.             break;
  1704.         }
  1705.         case 'h':
  1706.             fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
  1707.             hints = 0;
  1708.             break;
  1709.         case 'H':
  1710.             fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
  1711.             fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
  1712.             subhints = 0;
  1713.             break;
  1714.         case 'f':
  1715.             fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
  1716.             trybold = 0;
  1717.             break;
  1718.         case 'w':
  1719.             fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
  1720.             correctwidth = 1;
  1721.             break;
  1722.         case 'u':
  1723.             if(wantuid) {
  1724.                 fprintf(stderr, "**** UniqueID may be specified only once ****\n");
  1725.                 exit(1);
  1726.             }
  1727.             wantuid = 1; 
  1728.             if(optarg[0]=='A' && optarg[1]==0)
  1729.                 strUID=0; /* will be generated automatically */
  1730.             else {
  1731.                 strUID=optarg;
  1732.                 for(i=0; optarg[i]!=0; i++)
  1733.                     if( !isdigit(optarg[i]) ) {
  1734.                         fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
  1735.                         exit(1);
  1736.                     }
  1737.             }
  1738.             break;
  1739.         case 'v':
  1740.             correctvsize = atoi(optarg);
  1741.             if(correctvsize <= 0 && correctvsize > 1000) {
  1742.                 fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
  1743.                 correctvsize=0;
  1744.             }
  1745.             break;
  1746.         case 'p':
  1747.             if(cursw!=0) {
  1748.                 fprintf(stderr, "**** only one front-end parser be used ****\n");
  1749.                 exit(1);
  1750.             }
  1751.  
  1752.             { /* separate parser from parser-specific argument */
  1753.                 char *p = strchr(optarg, LANG_ARG_SEP);
  1754.                 if(p != 0) {
  1755.                     *p = 0;
  1756.                     front_arg = p+1;
  1757.                 } else
  1758.                     front_arg = "";
  1759.             }
  1760.             for(i=0; frontswtab[i] != NULL; i++)
  1761.                 if( !strcmp(frontswtab[i]->name, optarg) ) {
  1762.                     cursw = frontswtab[i];
  1763.                     break;
  1764.                 }
  1765.  
  1766.             if(cursw==0) {
  1767.                 if (strcmp(optarg, "?"))
  1768.                   fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
  1769.                 fputs("the following front-ends are supported now:\n", stderr);
  1770.                 for(i=0; frontswtab[i] != NULL; i++) {
  1771.                     fprintf(stderr,"  %s (%s)\n   file suffixes: ", 
  1772.                         frontswtab[i]->name,
  1773.                         frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
  1774.                     );
  1775.                     for(j=0; j<MAXSUFFIX; j++)
  1776.                         if(frontswtab[i]->suffix[j])
  1777.                             fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
  1778.                     fprintf(stderr, "\n");
  1779.                 }
  1780.                 exit(1);
  1781.             }
  1782.             break;
  1783.         case 'l':
  1784.             if(uni_lang_selected!=0) {
  1785.                 fprintf(stderr, "**** only one language option may be used ****\n");
  1786.                 exit(1);
  1787.             }
  1788.  
  1789.             { /* separate language from language-specific argument */
  1790.                 char *p = strchr(optarg, LANG_ARG_SEP);
  1791.                 if(p != 0) {
  1792.                     *p = 0;
  1793.                     uni_lang_arg = p+1;
  1794.                 } else
  1795.                     uni_lang_arg = "";
  1796.             }
  1797.             for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
  1798.                 if( !strcmp(uni_lang[i].name, optarg) ) {
  1799.                     uni_lang_selected = &uni_lang[i];
  1800.                     uni_sample = uni_lang[i].sample_upper;
  1801.                     break;
  1802.                 }
  1803.  
  1804.             if(uni_lang_selected==0) {
  1805.                 if (strcmp(optarg, "?"))
  1806.                     fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
  1807.                 fputs("       the following languages are supported now:\n", stderr);
  1808.                 for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
  1809.                     fprintf(stderr,"         %s (%s)\n", 
  1810.                         uni_lang[i].name,
  1811.                         uni_lang[i].descr ? uni_lang[i].descr : "no description"
  1812.                     );
  1813.                 exit(1);
  1814.             }
  1815.             break;
  1816.         case 'L':
  1817.             if(uni_lang_selected!=0) {
  1818.                 fprintf(stderr, "**** only one language option may be used ****\n");
  1819.                 exit(1);
  1820.             }
  1821.             uni_lang_selected = &uni_lang_user;
  1822.             uni_lang_arg = optarg;
  1823.             break;
  1824.         case 'V':
  1825.             printversion();
  1826.             exit(0);
  1827.             break;
  1828.         default:
  1829.             usage();
  1830.             exit(1);
  1831.             break;
  1832.         }
  1833.     }
  1834.     argc-=optind-1; /* the rest of code counts from argv[0] */
  1835.     argv+=optind-1;
  1836.  
  1837.     if (absolute && encode) {
  1838.         fprintf(stderr, "**** options -a and -e are incompatible ****\n");
  1839.         exit(1);
  1840.     }
  1841.         if ((argc != 2) && (argc != 3)) {
  1842.         usage();
  1843.         exit(1);
  1844.     }
  1845.  
  1846.     /* try to guess the language by the locale used */
  1847.     if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
  1848.         for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
  1849.             if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
  1850.                 uni_lang_selected = &uni_lang[i];
  1851.                 goto got_a_language;
  1852.             }
  1853.         }
  1854.         /* no full name ? try aliases */
  1855.         for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
  1856.             for(c=0; c<MAXUNIALIAS; c++)
  1857.                 if( uni_lang[i].alias[c]!=0
  1858.                 && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
  1859.                     uni_lang_selected = &uni_lang[i];
  1860.                     goto got_a_language;
  1861.                 }
  1862.         }
  1863.     got_a_language:
  1864.         if(uni_lang_selected!=0) {
  1865.             WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
  1866.             uni_sample = uni_lang[i].sample_upper;
  1867.         }
  1868.     }
  1869.  
  1870.     /* try to guess the front-end parser by the file name suffix */
  1871.     if(cursw==0) {
  1872.         char *p = strrchr(argv[1], '.');
  1873.         char *s;
  1874.  
  1875.         if(p!=0 && (s = strdup(p+1))!=0) {
  1876.             for(p=s; *p; p++)
  1877.                 *p = tolower(*p);
  1878.             p = s;
  1879.  
  1880.             for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
  1881.                 for(j=0; j<MAXSUFFIX; j++)
  1882.                     if(frontswtab[i]->suffix[j]
  1883.                     && !strcmp(p, frontswtab[i]->suffix[j]) ) {
  1884.                         cursw = frontswtab[i];
  1885.                         WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
  1886.                             cursw->name);
  1887.                         WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
  1888.                         break;
  1889.                     }
  1890.             }
  1891.             free(s);
  1892.         }
  1893.  
  1894.         if(cursw==0) {
  1895.             cursw = frontswtab[0];
  1896.             WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n", 
  1897.                 cursw->name);
  1898.             WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
  1899.         }
  1900.     }
  1901.  
  1902.     /* open the input file */
  1903.     cursw->open(argv[1], front_arg);
  1904.  
  1905.         /* Get base name of output file (if not specified)
  1906.      * by removing (known) suffixes
  1907.      */
  1908.         if (argc == 2) {
  1909.             char *p;
  1910.                 argv[2] = strdup (argv[1]);
  1911.         p = strrchr(argv[2], '.');
  1912.             if (p != NULL)
  1913.           for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
  1914.              if (!strcmp(p+1, cursw->suffix[j])) {
  1915.               *p = '\0';
  1916.               break;
  1917.             }
  1918.     }
  1919.  
  1920.     if (argv[2][0] == '-' && argv[2][1] == 0) {
  1921.         pfa_file = stdout;
  1922. #ifdef WINDOWS
  1923.         if(encode) {
  1924.             fprintf(stderr, "**** can't write encoded file to stdout ***\n");
  1925.             exit(1);
  1926.         }
  1927. #endif /* WINDOWS */
  1928.         if ((afm_file = fopen(BITBUCKET, "w+")) == NULL) {
  1929.             fprintf(stderr, "**** Cannot open %s ****\n",
  1930.                 BITBUCKET);
  1931.             exit(1);
  1932.         }
  1933.         if(wantafm) { /* print .afm instead of .pfa */
  1934.             FILE *n;
  1935.             n=pfa_file;
  1936.             pfa_file=afm_file;
  1937.             afm_file=n;
  1938.         }
  1939.     } else {
  1940. #ifndef WINDOWS
  1941.         sprintf(filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
  1942. #else /* WINDOWS */
  1943.         sprintf(filename, "%s.t1a", argv[2]);
  1944. #endif /* WINDOWS */
  1945.         if ((pfa_file = fopen(filename, "w+b")) == NULL) {
  1946.             fprintf(stderr, "**** Cannot create %s ****\n", filename);
  1947.             exit(1);
  1948.         } else {
  1949.             WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
  1950.         }
  1951.  
  1952.         sprintf(filename, "%s.afm", argv[2]) ;
  1953.         if ((afm_file = fopen(filename, "w+")) == NULL) {
  1954.             fprintf(stderr, "**** Cannot create %s ****\n", filename);
  1955.             exit(1);
  1956.         }
  1957.     }
  1958.  
  1959.     /*
  1960.      * Now check whether we want a fully encoded .pfa file
  1961.      */
  1962. #ifndef WINDOWS
  1963.     if (encode) {
  1964.         int             p[2];
  1965.         extern FILE    *ifp, *ofp;    /* from t1asm.c */
  1966.  
  1967.         ifp=stdin;
  1968.         ofp=stdout;
  1969.  
  1970.         if (pipe(p) < 0) {
  1971.             perror("**** Cannot create pipe ****\n");
  1972.             exit(1);
  1973.         }
  1974.         ofp = pfa_file;
  1975.         ifp = fdopen(p[0], "r");
  1976.         if (ifp == NULL) {
  1977.             perror("**** Cannot use pipe for reading ****\n");
  1978.             exit(1);
  1979.         }
  1980.         pfa_file = fdopen(p[1], "w");
  1981.         if (pfa_file == NULL) {
  1982.             perror("**** Cannot use pipe for writing ****\n");
  1983.             exit(1);
  1984.         }
  1985.         switch (fork()) {
  1986.         case -1:
  1987.             perror("**** Cannot fork the assembler process ****\n");
  1988.             exit(1);
  1989.         case 0:    /* child */
  1990.             fclose(pfa_file);
  1991.             exit(runt1asm(pfbflag));
  1992.         default: /* parent */
  1993.             fclose(ifp); fclose(ofp);
  1994.         }
  1995.     }
  1996. #endif /* WINDOWS */
  1997.  
  1998.     numglyphs = cursw->nglyphs();
  1999.  
  2000.     WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
  2001.  
  2002.     glyph_list = (GLYPH *) calloc(numglyphs,  sizeof(GLYPH));
  2003.  
  2004.     /* initialize non-0 fields */
  2005.     for (i = 0; i < numglyphs; i++) {
  2006.         GLYPH *g;
  2007.  
  2008.         g = &glyph_list[i];
  2009.         g->char_no = -1;
  2010.         g->orig_code = -1;
  2011.         g->name = "UNKNOWN";
  2012.         g->flags = GF_FLOAT; /* we start with float representation */
  2013.     }
  2014.  
  2015.     handle_gnames();
  2016.  
  2017.     cursw->glmetrics(glyph_list);
  2018.     cursw->fnmetrics(&fontm);
  2019.  
  2020.     original_scale_factor = 1000.0 / (double) fontm.units_per_em;
  2021.  
  2022.     if(transform == 0)
  2023.         scale_factor = 1.0; /* don't transform */
  2024.     else
  2025.         scale_factor = original_scale_factor;
  2026.  
  2027.     if(correctvsize && uni_sample!=0) { /* only for known languages */
  2028.         /* try to adjust the scale factor to make a typical
  2029.          * uppercase character of hight at least (correctvsize), this
  2030.          * may improve the appearance of the font but also
  2031.          * make it weird, use with caution
  2032.          */
  2033.         int ysz;
  2034.  
  2035.         ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
  2036.         if( ysz<correctvsize ) {
  2037.             scale_factor *= (double)correctvsize / ysz;
  2038.         }
  2039.     }
  2040.  
  2041.     if(allglyphs) {
  2042.         for (i = 0; i < numglyphs; i++) {
  2043.             glyph_list[i].flags |= GF_USED;
  2044.         }
  2045.     } else {
  2046.         for (i = 0; i < ENCTABSZ; i++) {
  2047.             glyph_list[encoding[i]].flags |= GF_USED;
  2048.         }
  2049.  
  2050.         /* also always include .notdef */
  2051.         for (i = 0; i < numglyphs; i++) 
  2052.             if(!strcmp(glyph_list[i].name, ".notdef")) {
  2053.                 glyph_list[i].flags |= GF_USED;
  2054.                 break;
  2055.             }
  2056.     }
  2057.  
  2058.     for (i = 0; i < numglyphs; i++) {
  2059.         if (glyph_list[i].flags & GF_USED) {
  2060.             DBG_TO_GLYPH(&glyph_list[i]);
  2061.             convert_glyf(i);
  2062.             DBG_FROM_GLYPH(&glyph_list[i]);
  2063.         }
  2064.     }
  2065.  
  2066.     italic_angle = fontm.italic_angle;
  2067.  
  2068.     if (italic_angle > 45.0 || italic_angle < -45.0)
  2069.         italic_angle = 0.0;    /* consider buggy */
  2070.  
  2071.     if (hints) {
  2072.         findblues();
  2073.         for (i = 0; i < numglyphs; i++) {
  2074.             if (glyph_list[i].flags & GF_USED) {
  2075.                 DBG_TO_GLYPH(&glyph_list[i]);
  2076.                 buildstems(&glyph_list[i]);
  2077.                 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
  2078.                 DBG_FROM_GLYPH(&glyph_list[i]);
  2079.             }
  2080.         }
  2081.         stemstatistics();
  2082.     } else {
  2083.         for(i=0; i<4; i++)
  2084.             bbox[i] = iscale(fontm.bbox[i]);
  2085.     }
  2086.     /* don't touch the width of fixed width fonts */
  2087.     if( fontm.is_fixed_pitch )
  2088.         correctwidth=0;
  2089.     docorrectwidth(); /* checks correctwidth inside */
  2090.     if (reverse)
  2091.         for (i = 0; i < numglyphs; i++) {
  2092.             if (glyph_list[i].flags & GF_USED) {
  2093.                 DBG_TO_GLYPH(&glyph_list[i]);
  2094.                 reversepaths(&glyph_list[i]);
  2095.                 assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
  2096.                 DBG_FROM_GLYPH(&glyph_list[i]);
  2097.             }
  2098.         }
  2099.  
  2100.  
  2101. #if 0
  2102.     /*
  2103.     ** It seems to bring troubles. The problem is that some
  2104.     ** styles of the font may be recognized as fixed-width
  2105.     ** while other styles of the same font as proportional.
  2106.     ** So it's better to be commented out yet.
  2107.     */
  2108.     if (tryfixed) 
  2109.         alignwidths();
  2110. #endif
  2111.  
  2112.     if(trybold) {
  2113.         forcebold = fontm.force_bold;
  2114.     }
  2115.  
  2116.     fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
  2117.     time(&now);
  2118.     fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
  2119.     fprintf(pfa_file, "%% Converted from TrueType font %s by ttf2pt1 %s/%s\n%%\n", argv[1], TTF2PT1_VERSION, cursw->name);
  2120.     fprintf(pfa_file, "%%%%EndComments\n");
  2121.     fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
  2122.  
  2123.     WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
  2124.  
  2125.  
  2126.     fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version);
  2127.  
  2128.     fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright);
  2129.  
  2130.     fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full);
  2131.     fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family);
  2132.  
  2133.     if(wantuid) {
  2134.         if(strUID)
  2135.             fprintf(pfa_file, "/UniqueID %s def\n", strUID);
  2136.         else {
  2137.             numUID=0;
  2138.             for(i=0; fontm.name_full[i]!=0; i++) {
  2139.                 numUID *= 37; /* magic number, good for hash */
  2140.                 numUID += fontm.name_full[i]-' ';
  2141.                 /* if the name is long the first chars
  2142.                  * may be lost forever, so re-insert
  2143.                  * them thus making kind of CRC
  2144.                  */
  2145.                 numUID += (numUID>>24) & 0xFF;
  2146.             }
  2147.             /* the range for private UIDs is 4 000 000 - 4 999 999 */
  2148.             fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
  2149.         }
  2150.     }
  2151.  
  2152.     fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style);
  2153.  
  2154.     fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle);
  2155.     fprintf(pfa_file, "/isFixedPitch %s def\n",
  2156.         fontm.is_fixed_pitch ? "true" : "false");
  2157.  
  2158.     /* we don't print out the unused glyphs */
  2159.     nchars = 0;
  2160.     for (i = 0; i < numglyphs; i++) {
  2161.         if (glyph_list[i].flags & GF_USED) {
  2162.             nchars++;
  2163.         }
  2164.     }
  2165.  
  2166.     fprintf(afm_file, "StartFontMetrics 4.1\n");
  2167.     fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
  2168.     fprintf(afm_file, "FullName %s\n", fontm.name_full);
  2169.     fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
  2170.     fprintf(afm_file, "EncodingScheme FontSpecific\n");
  2171.     fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
  2172.     fprintf(afm_file, "Weight %s\n", fontm.name_style);
  2173.     fprintf(afm_file, "Version %s\n", fontm.name_version);
  2174.     fprintf(afm_file, "Characters %d\n", nchars);
  2175.     fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
  2176.  
  2177.     fprintf(afm_file, "Ascender %d\n", fontm.ascender);
  2178.     fprintf(afm_file, "Descender %d\n", fontm.descender);
  2179.  
  2180.     fprintf(pfa_file, "/UnderlinePosition %d def\n",
  2181.         iscale(fontm.underline_position));
  2182.  
  2183.     fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n",
  2184.         iscale(fontm.underline_thickness));
  2185.  
  2186.     fprintf(afm_file, "UnderlineThickness %d\n",
  2187.         iscale(fontm.underline_thickness));
  2188.  
  2189.     fprintf(afm_file, "UnderlinePosition %d\n",
  2190.         iscale(fontm.underline_position));
  2191.  
  2192.     fprintf(afm_file, "IsFixedPitch %s\n",
  2193.         fontm.is_fixed_pitch ? "true" : "false");
  2194.     fprintf(afm_file, "FontBBox %d %d %d %d\n",
  2195.         bbox[0], bbox[1], bbox[2], bbox[3]);
  2196.  
  2197.     fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
  2198.     fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
  2199.     /* I'm not sure if these are fixed */
  2200.     fprintf(pfa_file, "/FontType 1 def\n");
  2201.  
  2202.     if (transform) {
  2203.         fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
  2204.     } else {
  2205.         fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
  2206.             original_scale_factor / 1000.0, original_scale_factor / 1000.0);
  2207.     }
  2208.  
  2209.     fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
  2210.         bbox[0], bbox[1], bbox[2], bbox[3]);
  2211.  
  2212.     fprintf(pfa_file, "/Encoding 256 array\n");
  2213.     /* determine number of elements for metrics table */
  2214.     nmetrics = 256;
  2215.      for (i = 0; i < numglyphs; i++) {
  2216.         if( glyph_list[i].flags & GF_USED 
  2217.         && glyph_list[i].char_no == -1 ) {
  2218.             nmetrics++;
  2219.         }
  2220.     }
  2221.     fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
  2222.  
  2223.      for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
  2224.         fprintf(pfa_file,
  2225.             "dup %d /%s put\n", i, glyph_list[encoding[i]].name);
  2226.         if( glyph_list[encoding[i]].flags & GF_USED )  {
  2227.             print_glyph_metrics(i, encoding[i]);
  2228.         }
  2229.     }
  2230.  
  2231.     /* print the metrics for glyphs not in encoding table */
  2232.     for(i=0; i<numglyphs; i++) {
  2233.         if( (glyph_list[i].flags & GF_USED)
  2234.         && glyph_list[i].char_no == -1 ) {
  2235.             print_glyph_metrics(-1, i);
  2236.         }
  2237.     }
  2238.  
  2239.     fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
  2240.     fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
  2241.  
  2242.     fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
  2243.     fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
  2244.     fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
  2245.  
  2246.     /* UniqueID must be shown twice, in both font and Private dictionary */
  2247.     if(wantuid) {
  2248.         if(strUID)
  2249.             fprintf(pfa_file, "/UniqueID %s def\n", strUID);
  2250.         else
  2251.             fprintf(pfa_file, "/UniqueID %lu def\n", numUID);
  2252.     }
  2253.  
  2254.     if(forcebold==0)
  2255.         fprintf(pfa_file, "/ForceBold false def\n");
  2256.     else if(forcebold==1)
  2257.         fprintf(pfa_file, "/ForceBold true def\n");
  2258.  
  2259.     fprintf(pfa_file, "/BlueValues [ ");
  2260.     for (i = 0; i < nblues; i++)
  2261.         fprintf(pfa_file, "%d ", bluevalues[i]);
  2262.     fprintf(pfa_file, "] def\n");
  2263.  
  2264.     fprintf(pfa_file, "/OtherBlues [ ");
  2265.     for (i = 0; i < notherb; i++)
  2266.         fprintf(pfa_file, "%d ", otherblues[i]);
  2267.     fprintf(pfa_file, "] def\n");
  2268.  
  2269.     if (stdhw != 0)
  2270.         fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
  2271.     if (stdvw != 0)
  2272.         fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
  2273.     fprintf(pfa_file, "/StemSnapH [ ");
  2274.     for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
  2275.         fprintf(pfa_file, "%d ", stemsnaph[i]);
  2276.     fprintf(pfa_file, "] def\n");
  2277.     fprintf(pfa_file, "/StemSnapV [ ");
  2278.     for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
  2279.         fprintf(pfa_file, "%d ", stemsnapv[i]);
  2280.     fprintf(pfa_file, "] def\n");
  2281.  
  2282.     fprintf(pfa_file, "/MinFeature {16 16} def\n");
  2283.     /* Are these fixed also ? */
  2284.     fprintf(pfa_file, "/password 5839 def\n");
  2285.  
  2286.     /* calculate the number of subroutines */
  2287.  
  2288.     subid=5;
  2289.     for (i = 0; i < numglyphs; i++) {
  2290.         if (glyph_list[i].flags & GF_USED) {
  2291.             subid+=glyph_list[i].nsg;
  2292.         }
  2293.     }
  2294.  
  2295.     fprintf(pfa_file, "/Subrs %d array\n", subid);
  2296.     /* standard subroutines */
  2297.     fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
  2298.     fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
  2299.     fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
  2300.     fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
  2301.     /* our sub to make the hint substitution code shorter */
  2302.     fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
  2303.  
  2304.     /* print the hinting subroutines */
  2305.     subid=5;
  2306.     for (i = 0; i < numglyphs; i++) {
  2307.         if (glyph_list[i].flags & GF_USED) {
  2308.             subid+=print_glyph_subs(i, subid);
  2309.         }
  2310.     }
  2311.  
  2312.     fprintf(pfa_file, "ND\n");
  2313.  
  2314.     fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
  2315.  
  2316.     for (i = 0; i < numglyphs; i++) {
  2317.         if (glyph_list[i].flags & GF_USED) {
  2318.             print_glyph(i);
  2319.         }
  2320.     }
  2321.  
  2322.  
  2323.     fprintf(pfa_file, "end\nend\nreadonly put\n");
  2324.     fprintf(pfa_file, "noaccess put\n");
  2325.     fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
  2326.     fprintf(pfa_file, "mark currentfile closefile\n");
  2327.     fprintf(pfa_file, "cleartomark\n");
  2328.     fclose(pfa_file);
  2329.  
  2330.     fprintf(afm_file, "EndCharMetrics\n");
  2331.  
  2332.     /* print the kerning data if present */
  2333.     cursw->kerning(glyph_list);
  2334.     print_kerning(afm_file);
  2335.  
  2336.     fprintf(afm_file, "EndFontMetrics\n");
  2337.     fclose(afm_file);
  2338.  
  2339.     WARNING_1 fprintf(stderr, "Finished - font files created\n");
  2340.  
  2341.     cursw->close();
  2342.  
  2343. #ifndef WINDOWS
  2344.     while (wait(&ws) > 0) {
  2345.     }
  2346. #else 
  2347.     if (encode) {
  2348.         extern FILE    *ifp, *ofp;    /* from t1asm.c */
  2349.  
  2350.         sprintf(filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
  2351.  
  2352.         if ((ofp = fopen(filename, "w+b")) == NULL) {
  2353.             fprintf(stderr, "**** Cannot create %s ****\n", filename);
  2354.             exit(1);
  2355.         } else {
  2356.             WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
  2357.         }
  2358.  
  2359.         sprintf(filename, "%s.t1a", argv[2]);
  2360.  
  2361.         if ((ifp = fopen(filename, "rb")) == NULL) {
  2362.             fprintf(stderr, "**** Cannot read %s ****\n", filename);
  2363.             exit(1);
  2364.         } else {
  2365.             WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
  2366.         }
  2367.  
  2368.         runt1asm(pfbflag);
  2369.  
  2370.         WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
  2371.         if(unlink(filename) < 0) 
  2372.             WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);
  2373.     }
  2374. #endif /* WINDOWS */
  2375.  
  2376.     return 0;
  2377. }
  2378.